﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Threading.Tasks;
using Cosmos.Core.IOGroup;
using Cosmos.Core.Plugs;
using DimOS.Constants;
using DimOS.DimFS;
using DimOS.DimSH;
using DimOS.Internals;
using SYS = Cosmos.System;
using HAL = Cosmos.Hardware;
using CORE = Cosmos.Core;
using System.Text.RegularExpressions;
using Cosmos.Assembler.x86;
using DimOS.Modules;
using DimOS.Plugs;
using DimOS.VTS;
using Console = System.Console;
using String = System.String;
using UI = DimOS.DimSH.Interface;
using TERM = DimOS.DimSH.Terminal;
using SH = DimOS.DimSH.Shell;
using BF = DimOS.Brainfuck;
using Convert = DimOS.Plugs.Convert;


namespace DimOS
{
    //TODO: Get rid of this cr*ap
    // ReSharper disable SpecifyACultureInStringConversionExplicitly
    public class Kernel : SYS.Kernel
    {
        private static string _splitter = ""; //Splitter line which is used in Split() method
        private static string _spaceSplitter = ""; //Eraser line (actually a splitter made of spaces) which is used for clearing certain parts of the screen
        private static string _prompt = "user"; //Prompt for command line section
        private static string _password = ""; //Password for root-access mode
        private const string Version = "0.3 (Build 378)"; //Version string
        private static readonly int Cols = new HAL.TextScreen().Cols; //Number of columns on the TextScreen
        private static readonly int Rows = new HAL.TextScreen().Rows; //Number of rows on the TextScreen
        private static readonly int OutputCols = Cols - 14; //Number of columns available for output section
        private static int _targets; //Stores the number of accomplished targets
        private static int _quizzes; //Stores the number of completed quizzes
        private static int _guesses; //Stores the number of guesses in the word guessing game
        private static bool _root; //Indicates whether the user has a full access to the OS resources 
        private static readonly string[] StringKey = new string[10000]; //Stores the keys of strings
        private static readonly string[] StringValue = new string[StringKey.Length]; //Stores the value of strings
        private static int _index; //Position of new string in string buffer 
        private static int _factsIndex; //Index of next fact
        private static readonly List<string> Facts = new List<string> { "Bill Gates wrote a class scheduling program for his school. He tweaked the program’s code so that he was placed in classes with mostly female students.", "The first Windows virus was called Winver 1.4.", "As the newest operating Windows 8.1 is today, more than a handful billion of people uses windows and a least million are helping out by submitting feedbacks to mold what we use today. Also about 7-8 million beta testers and another for people who are just trying out the beta themselves.", "The Blue Screen of Death or BSOD also known as the BSD error or stop error, was phrased by Erik Noyes while he was working at Charles Schwab and Co., Inc as a technical support  in 1991. By then it spread and from then it became that name. and more or less 25 million people experience this event everyday all over the world.", "There are a couple of window operating system that never came into release and were cancelled, like the windows 96(Nashville) on May 3, 1996 or “Ciaro” - an object oriented operating system between 1997 and 1998. There is also the Windows Neptune on December 1999.", "Interface Manager was the original name for Windows when it was bought about, based on the Steve Jobs’ MAC Operating system on 1985.", "Windows Operating System has millions of line codes about 50 million and growing every time there’s a release and roughly 7000 people and in 34 countries and almost 200,000 supported devices.", "There are about 300,000 applications made for all the windows series made and counting.", "A musician named Brian Eno is the man behind making Windows 95 small alert of sounds and start-ups. He has worked with a few popular musicians in his days like U2 and David Bowie.", "60% of Windows Vista’s code was rewritten due to a lot of bugs and internal errors before it was properly released.", "Windows 7’s code name was “Blackcomb” and “Vienna”. They changed it then to Windows “7” which stands for 7th Operating system they have released.", "You cannot create a folder and name it “Con” anywhere in your Windows Operating System. Apparently a “con” folder was reserved for the old DOS to be used.", "Linux is a UNIX like free and open source operating system. However, Linux does not seek UNIX branding. Most Linux distributions prefers not to brand their distro as UNIX dues the costs for certification. Also, most businesses are well aware of the Linux brand.", "Linus Torvalds is the creator and chief architect of the Linux kernel. He now acts as the project’s coordinator. The name “Linux” comes from the Linux kernel, originally written in 1991 by Linus Torvalds. However, initially Torvalds wanted to call the kernel he developed as Freax. Torvalds owns the Linux trademark, and monitors use of it through the non-profit organization called LinuxInternational.", "About 2% of the Linux kernel were written by Torvalds himself. Today the Linux kernel has received contributions from thousands of developers across the globe. Torvalds remains the ultimate authority on what new code is incorporated into the standard Linux kernel hosted at kernel.org. However, Linux distribution modifies the kernel as per their user’s requirements.", "Linux has been built by a total of 13,036 contributors worldwide. The most prolific contributor is, of course, Linus Torvalds himself, who has committed code more than 20,000 times over the course of the lifetime of Linux. The following figures show the all-time top-10 contributors of Linux in terms of commit counts.", "The total source lines of code (SLOC) of Linux is over 17 million. The estimated cost for the entire code base is 5,526 person-years, or over 300M USD according to basic COCOMO model.", "The official mascot of Linux is \"Tux\", a friendly penguin character. The idea of using a cuddly penguin as a mascot/logo was in fact first conceived and asserted by Linus himself. Why penguin? Personally Linus is fond of penguins, despite the fact that he once was bitten by a ferocious penguin, causing him infected with a disease.", " A Linux \"distribution\" contains the Linux kernel, supporting GNU utilities/libraries, and other third-party applications. According to distrowatch.com, there are a total of 286 actively maintained Linux distrutions. The oldest among them is Slackware whose very first release 1.0 became available in 1993.", "The dominance of Linux on top 500 supercomputers continues to rise. As of June 2014, 97% of the world-fastest computers are powered by Linux.", "In 2000, Steve Jobs at Apple Inc. tried to hire Linus Torvalds to have him drop Linux development and instead work on \"Unix for the biggest user base,\" which was OS X back then. Linus declined the offer.", "The reboot() system call in the Linux kernel requires two magic numbers. The second magic number comes from the birth dates of Linus Torvalds and his three daughters.", "Linux kernels have weird and funny code names. For example, the code name for the latest kernel 4.0 is \"Hurr durr I'ma sheep.\" These code names are authored by Linus Torvalds himself, and included in the Makefile of their source trees." }; 
        private static readonly List<string> Targets = new List<string> { "Change the default dim (prompt in user-access mode) [....]", "Switch to the root-access mode [....]", "Set the password for root-access mode [....]", "Set a string in the string buffer [....]", "Switch back to the user-access mode [....]", "View the system information [....]", "View an interesting fact about Operating Systems [....]", "View the current root-access password [....]", "View any string from the string buffer [....]", "Calculate any expression [....]", "Set a stopwatch to 10 seconds [....]", "Clear the output screen [....]" };
        private static readonly List<string> Quizzes = new List<string> { "Microkernel is a small operating system core that provides the foundation for modular|1. Process|2. Programs|3. Application|4. Extensions[4]", "Processor-I/O involves data transferring between|1. Computers|2. Processor and I/O modules|3. Registers|4. User processes[2]", "At system boot of the computer system its hardware starts in|1. User mode|2. Kernel mode|3. Supervisor mode|4. Both 2 and 3[4]", "Example of bug in one program of the operating system that affects others is|1. Zero error|2. Infinite loop|3. Invalid memory access|4. Both 1 and 2[2]", "Authentication is the fundamental building block in most computers|1. Security context|2. Control context|3. Execution context|4. Performance context[1]", "Multiprogramming of the computer system increases|1. Memory|2. Storage|3. CPU utilization|4. Cost[3]", "Main memory of the computer system is also called|1. Non-volatile|2. Volatile|3. Reserved|4. Large[2]", "Controller of the computer system transfers data from device to|1. Buffers|2. Cache|3. Registers|4. Indexes[1]", "Asynchronous elements in the program can be implemented as|1. Bugs|2. Threads|3. Programs|4. Security Policy[2]", "Symmetric multiprocessing architecture of the computer system uses shared|1. Bus|2. Memory|3. Processors|4. Both 1 and 2[4]", "System call routines of the operating system are mostly written in|1. C|2. C++|3. Java|4. Both 1 and 2[4]", "One word memory storage is the collection of|1. 2 bytes|2. 4 bytes|3. 7 bytes|4. 8 bytes[4]" }; 
        private static readonly List<string> Guesses = new List<string> { "There is a term for loading an operating system into memory. What is it?[boot|booting]", "Which phenomenon occurs when the processor spends most of its time in swapping pages, rather than executing them?[thrashing]", "Transfer of information to and from main memory takes place in terms of...[words|word]", "Where does swap space reside?[disk|hdd]", "User action such as keystroke or mouse click is referred to as...[event]", "One megabyte of memory in the form of kilobytes is equal to...[1024]", "Thousands of system calls by the operating system are executed per...[second|sec]", "When a thread completes its register context stacks are d...[deallocated|de-allocated]", "Bourne-again-shells of the operating system are used by...[linux|unix]", "More devices can be connected to computer system through a c...[controller]", "Static programs of the computer system are stored in...[rom]", "Deadlock avoidance requires knowledge of future p...[process]" }; 
        //Initializes the OS, shows the boot process (i.e. loading modules)
        uint heap;

        protected override void BeforeRun()
        {
            //CORE.HMI.Init(); mStarted = true; CORE.HMI.GCMonitor(); CORE.HMI.GCFreeAll(); CORE.HMI.PrintMemoryUsed();

            //var screen = new HAL.VGAScreen();
            //screen.SetTextMode(HAL.VGAScreen.TextSize.Size80x25);
            
            Initialize.Self();
            Initialize.Logo();
            Initialize.Hardware();
            Initialize.FileSystem();
            Initialize.CommandShell();
            Initialize.Finish();
        }


        //Main method which manages prompt and processing of commands
        protected override void Run()
        {
            var limit = ((CORE.CPU.GetAmountOfRAM() + 2) * 1024 * 1024) - GC
            .Heap.MemoryUsed; string command; while (CORE.Heap.GetMemoryUse()
            <= limit) { command = SH.Prompt(0, UI.OutputColumns - 1, UI.Rows -
            1); TERM.ScrollEnd(); UI.X = 0; UI.Y = UI.Rows - 3; InputProcessor
            .Execute(command); /*H.UnitTests.Test();*/
            } Stop();
        }

        protected override void AfterRun()
        {
            
        }


        //Splits an output into parts, each part contains an output from a certain command
        private static void Split(bool drawClock = true, bool inline = true)
        {
            if (!drawClock) DimSH.Terminal.WriteLine("\n" + _splitter + "\n", false);
            else
            {
                var posX = Console.CursorLeft;
                var posY = Console.CursorTop;
                DimSH.Interface.ClearSections();
                SYS.Global.Console.X = 0;
                SYS.Global.Console.Y = Rows - 3;
                DimSH.Terminal.Write(_splitter, false);
                if (inline) DimSH.Terminal.WriteLine();
                SYS.Global.Console.X = posX;
                SYS.Global.Console.Y = posY;
                Interface.DrawSections();
            }
        }

        //DimSH.Terminal.Writes a loading indicator (a progress bar)
        private static void LoadingIndicator(int length, int returnPosition)
        {
            var color = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.White;
            DimSH.Terminal.Write("[", false);
            var orig = Console.CursorLeft;
            SYS.Global.Console.X = Console.CursorLeft + length;
            DimSH.Terminal.Write("]", false);
            SYS.Global.Console.X = orig;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Terminal.Wait(1);
            for (int i = 0; i < 10; i++)
            {
                DimSH.Terminal.Write("#", false);
                Terminal.Wait(1);
            }
            SYS.Global.Console.X = returnPosition;
            Console.ForegroundColor = color;
        }

        //DimSH.Terminal.Writes a placeholder for DONE indicator when the module starts loading
        private static int DoneIndicator()
        {
            var color = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.White;
            DimSH.Terminal.Write("<....>", false);
            Console.ForegroundColor = color;
            return Console.CursorLeft - 5;
        }

        //DimSH.Terminal.Writes DONE indicator when the module finishes loading
        private static void DoneIndicatorComplete(int position, int returnPosition)
        {
            var color = Console.ForegroundColor;
            SYS.Global.Console.X = position;
            Console.ForegroundColor = ConsoleColor.Green;
            DimSH.Terminal.Write("DONE", false);
            SYS.Global.Console.X = returnPosition;
            Console.ForegroundColor = color;
        }

        //DimSH.Terminal.Writes the information about the module being loaded to the output
        private static void LoadModule(string text, int loadingIndicatorLength, bool drawClock)
        {
            var pos = DoneIndicator();
            Console.ForegroundColor = ConsoleColor.White;
            DimSH.Terminal.Write(" " + text + " ", false);
            LoadingIndicator(loadingIndicatorLength, pos);
            DoneIndicatorComplete(pos, Console.CursorLeft);
            DimSH.Terminal.WriteLine(drawClock);
        }

        //Clears statistics in Information section (used to update positioning)
        private static void ClearStat()
        {
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 0;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 1;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 2;
            DimSH.Terminal.Write("              ", false);
        }

        //Clears sections from the screen (used to update positioning)
        private static void ClearSections()
        {
            var posX = Console.CursorLeft;
            var posY = Console.CursorTop;
            var color = Console.BackgroundColor;
            SYS.Global.Console.X = 0;
            SYS.Global.Console.Y = Rows - 2;
            DimSH.Terminal.Write(_spaceSplitter, false);
            Console.BackgroundColor = ConsoleColor.Gray;
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 9;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 8;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 7;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 6;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 4;
            DimSH.Terminal.Write("              ", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 3;
            DimSH.Terminal.Write("              ", false);
            ClearStat();
            SYS.Global.Console.X = posX;
            SYS.Global.Console.Y = posY;
            Console.BackgroundColor = color;
        }

        //Divides the screen into sections and renders some textual information
        public static void DrawSections()
        {
            var posX = Console.CursorLeft;
            var posY = Console.CursorTop;
            var colorF = Console.ForegroundColor;
            var colorB = Console.BackgroundColor;
            SYS.Global.Console.X = 0;
            SYS.Global.Console.Y = Rows - 2;
            Console.BackgroundColor = ConsoleColor.Cyan;
            //
            //Console.ForegroundColor = ConsoleColor.DarkRed;
            //DimSH.Terminal.Write("#", false);
            //Console.ForegroundColor = ConsoleColor.Yellow;
            //DimSH.Terminal.Write(">", false);
            //Console.ForegroundColor = ConsoleColor.DarkRed;
            //DimSH.Terminal.Write("user", false);
            //Console.ForegroundColor = ConsoleColor.Yellow;
            //DimSH.Terminal.Write(">", false);
            //Console.ForegroundColor = ConsoleColor.DarkRed;
            //DimSH.Terminal.Write("home", false);
            //Console.ForegroundColor = ConsoleColor.Yellow;
            //DimSH.Terminal.Write(">", false);
            //if (_spaceSplitter.Length == 66) _spaceSplitter = _spaceSplitter.Remove(54);
            //
            DimSH.Terminal.Write(_spaceSplitter, false);
            Console.BackgroundColor = ConsoleColor.Gray;
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 8;
            Console.ForegroundColor = ConsoleColor.Yellow;
            DimSH.Terminal.Write("dim.?", false);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            DimSH.Terminal.Write(":userprog", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 7;
            Console.ForegroundColor = ConsoleColor.Yellow;
            DimSH.Terminal.Write("set.?", false);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            DimSH.Terminal.Write(":setshell", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 6;
            Console.ForegroundColor = ConsoleColor.Yellow;
            DimSH.Terminal.Write("get.?", false);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            DimSH.Terminal.Write(":getshell", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 5;
            Console.ForegroundColor = ConsoleColor.Yellow;
            DimSH.Terminal.Write("cls.?", false);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            DimSH.Terminal.Write(":clearscr", false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 3;
            Console.ForegroundColor = ConsoleColor.DarkBlue;
            DimSH.Terminal.Write("Date: ", false);
            Console.ForegroundColor = ConsoleColor.Blue;
            DimSH.Terminal.Write(
                (HAL.RTC.DayOfTheMonth < 10 ? "0" + HAL.RTC.DayOfTheMonth : HAL.RTC.DayOfTheMonth.ToString())
                + "." +
                (HAL.RTC.Month < 10 ? "0" + HAL.RTC.Month : HAL.RTC.Month.ToString())
                + "." +
                HAL.RTC.Year,
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = Rows - 2;
            Console.ForegroundColor = ConsoleColor.DarkBlue;
            DimSH.Terminal.Write(
                "Time: " +
                (HAL.RTC.Hour < 10 ? "0" + HAL.RTC.Hour : HAL.RTC.Hour.ToString())
                + ":" +
                (HAL.RTC.Minute < 10 ? "0" + HAL.RTC.Minute : HAL.RTC.Minute.ToString())
                + ":" +
                (HAL.RTC.Second < 10 ? "0" + HAL.RTC.Second : HAL.RTC.Second.ToString()),
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 0;
            Console.ForegroundColor = ConsoleColor.DarkRed;
            DimSH.Terminal.Write(
                "Current Topic:",
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 1;
            Console.ForegroundColor = ConsoleColor.DarkGray;
            DimSH.Terminal.Write(
                (HAL.RTC.Month < 10).ToString(),
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 3;
            Console.ForegroundColor = ConsoleColor.DarkMagenta;
            DimSH.Terminal.Write(
                "Targets: " + (_targets < 10 ? "0" + _targets : _targets.ToString()) + "/" + (Targets.Count < 10 ? "0" + Targets.Count : Targets.Count.ToString()),
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 4;
            DimSH.Terminal.Write(
                "Quizzes: " + (_quizzes < 10 ? "0" + _quizzes : _quizzes.ToString()) + "/" + (Quizzes.Count < 10 ? "0" + Quizzes.Count : Quizzes.Count.ToString()),
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 5;
            DimSH.Terminal.Write(
                "Guesses: " + (_guesses < 10 ? "0" + _guesses : _guesses.ToString()) + "/" + (Guesses.Count < 10 ? "0" + Guesses.Count : Guesses.Count.ToString()),
                false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 6;
            DimSH.Terminal.Write(
                "Options: 00/00"// + (_guesses < 10 ? "0" + _guesses : _guesses.ToString()) + "/" + (Guesses.Count < 10 ? "0" + Guesses.Count : Guesses.Count.ToString()),
                ,false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 7;
            DimSH.Terminal.Write(
                "Matches: 00/00"// + (_guesses < 10 ? "0" + _guesses : _guesses.ToString()) + "/" + (Guesses.Count < 10 ? "0" + Guesses.Count : Guesses.Count.ToString()),
                ,false);
            SYS.Global.Console.X = OutputCols;
            SYS.Global.Console.Y = 8;
            DimSH.Terminal.Write(
                "Scripts: 00/00"// + (_guesses < 10 ? "0" + _guesses : _guesses.ToString()) + "/" + (Guesses.Count < 10 ? "0" + Guesses.Count : Guesses.Count.ToString()),
                ,false);
            
            //DimSH.Terminal.Write(Symbols.CornerBottomLeft + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.BorderHorizontal + Symbols.CornerBottomRight, false);
            SYS.Global.Console.X = posX;
            SYS.Global.Console.Y = posY;

            Console.ForegroundColor = colorF;
            Console.BackgroundColor = colorB;
        }

        // DimSH.Terminal.Writes a new line to the output
        private static void WriteLine(bool drawClock = true)
        {
            if (!drawClock) Console.WriteLine();
            else
            {
                var posX = Console.CursorLeft;
                var posY = Console.CursorTop;
                DimSH.Interface.ClearSections();
                SYS.Global.Console.X = 0;
                SYS.Global.Console.Y = Rows - 3;
                Console.WriteLine();
                Console.WriteLine();
                Console.WriteLine();
                SYS.Global.Console.X = posX;
                SYS.Global.Console.Y = posY;
                Interface.DrawSections();
            }
        }

        //Overload: DimSH.Terminal.Writes a specific text to the output with addition of a new line
        public static void WriteLine(string text, bool drawClock = true, bool autoFormatting = true)
        {
            if (!drawClock) Console.WriteLine(text);
            else
            {
                string[] finalText;
                if (autoFormatting)
                {
                    var fitText = "";
                    var fitTextList = new List<string>();
                    var textCopy = text;
                    var j = -1;
                    for (int i = 0; i < text.Length; i++)
                    {
                        j++;
                        if (j == OutputCols && i != text.Length - 1)
                        {
                            fitTextList.Add(text.Substring(i - j, j));
                            textCopy = textCopy.Remove(0, j);
                            j = 0;
                        }
                    }
                    fitTextList.Add(textCopy);
                    for (int i = 0; i < fitTextList.Count; i++)
                    {
                        if (fitTextList[i][0] == ' ') fitTextList[i] = fitTextList[i].Remove(0, 1);
                        if (fitTextList[i].Length < OutputCols && i != fitTextList.Count - 1)
                        {
                            var difference = OutputCols - fitTextList[i].Length;
                            fitTextList[i] += fitTextList[i + 1].Substring(0, difference);
                            fitTextList[i + 1] = fitTextList[i + 1].Remove(0, difference);
                        }
                        fitText += fitTextList[i] + "\n";
                    }
                    fitText = fitText.Remove(fitText.Length - 1, 1);
                    finalText = fitText.Split(new[] { "\n" }, StringSplitOptions.None);
                }
                else finalText = text.Split(new[] { "\n" }, StringSplitOptions.None);
                // ReSharper disable once ForCanBeConvertedToForeach
                for (int i = 0; i < finalText.Length; i++)
                {
                    var posX = Console.CursorLeft;
                    var posY = Console.CursorTop;
                    DimSH.Interface.ClearSections();
                    SYS.Global.Console.X = 0;
                    SYS.Global.Console.Y = Rows - 3;
                    Console.WriteLine(finalText[i]);
                    Console.WriteLine();
                    Console.WriteLine();
                    SYS.Global.Console.X = posX;
                    SYS.Global.Console.Y = posY;
                    Interface.DrawSections();
                }
            }
        }

        //DimSH.Terminal.Writes a specific text to the output without addition of new line
        private static void Write(string text, bool drawClock = true, bool autoFormatting = true)
        {
            if (!drawClock) Console.Write(text);
            else
            {
                string[] finalText;
                if (autoFormatting)
                {
                    var fitText = "";
                    var fitTextList = new List<string>();
                    var textCopy = text;
                    var j = -1;
                    for (int i = 0; i < text.Length; i++)
                    {
                        j++;
                        if (j == OutputCols && i != text.Length - 1)
                        {
                            fitTextList.Add(text.Substring(i - j, j));
                            textCopy = textCopy.Remove(0, j);
                            j = 0;
                        }
                    }
                    fitTextList.Add(textCopy);
                    for (int i = 0; i < fitTextList.Count; i++)
                    {
                        if (fitTextList[i][0] == ' ') fitTextList[i] = fitTextList[i].Remove(0, 1);
                        if (fitTextList[i].Length < OutputCols && i != fitTextList.Count - 1)
                        {
                            var difference = OutputCols - fitTextList[i].Length;
                            fitTextList[i] += fitTextList[i + 1].Substring(0, difference);
                            fitTextList[i + 1] = fitTextList[i + 1].Remove(0, difference);
                        }
                        fitText += fitTextList[i] + "\n";
                    }
                    fitText = fitText.Remove(fitText.Length - 1, 1);
                    finalText = fitText.Split(new[] { "\n" }, StringSplitOptions.None);
                }
                else finalText = text.Split(new[] { "\n" }, StringSplitOptions.None);
                // ReSharper disable once ForCanBeConvertedToForeach
                for (int i = 0; i < finalText.Length; i++)
                {
                    var posY = Console.CursorTop;
                    SYS.Global.Console.Y = Rows - 3;
                    Console.Write(finalText[i]);
                    SYS.Global.Console.Y = posY;
                }
            }
        }

        //Reads an input from the user
        private static string ReadLine(bool drawClock = true)
        {
            if (drawClock)
            {
                var text = Console.ReadLine();
                var posX = Console.CursorLeft;
                var posY = Console.CursorTop;
                var color = Console.BackgroundColor;
                SYS.Global.Console.X = 0;
                SYS.Global.Console.Y = Rows - 3;
                DimSH.Terminal.Write(_spaceSplitter, false);
                Console.BackgroundColor = ConsoleColor.Gray;
                SYS.Global.Console.X = OutputCols;
                SYS.Global.Console.Y = Rows - 3;
                DimSH.Terminal.Write("              ", false);
                SYS.Global.Console.X = OutputCols;
                SYS.Global.Console.Y = Rows - 2;
                DimSH.Terminal.Write("              ", false);
                ClearStat();
                SYS.Global.Console.X = posX;
                SYS.Global.Console.Y = posY;
                Console.BackgroundColor = color;
                Interface.DrawSections();
                return text;
            }
            return Console.ReadLine();


            //string result = "";

            //string buffer = "";

            ////The key is read passing true for the intercept argument to prevent
            ////any characters from displaying when the Escape key is pressed.
            //ConsoleKeyInfo info = Console.ReadKey(true);
            //while (info.Key != ConsoleKey.Enter && info.Key != ConsoleKey.Escape && info.Key != ConsoleKey.UpArrow)
            //{
            //    Console.DimSH.Terminal.Write(info.KeyChar);
            //    buffer += info.KeyChar;
            //    info = Console.ReadKey(true);
            //}

            //if (info.Key == ConsoleKey.Enter)
            //{
            //    result = buffer;
            //}

            //    if (info.Key == ConsoleKey.UpArrow)
            //    {
            //        Console.DimSH.Terminal.Write("Test");
            //    }

            //if (drawClock)
            //{
            //    //var text = Console.ReadLine();
            //    var posX = Console.CursorLeft;
            //    var posY = Console.CursorTop;
            //    var color = Console.BackgroundColor;
            //    SYS.Global.Console.X = 0;
            //    SYS.Global.Console.Y = Rows - 3;
            //    DimSH.Terminal.Write(_spaceSplitter, false);
            //    Console.BackgroundColor = ConsoleColor.Gray;
            //    SYS.Global.Console.X = OutputCols;
            //    SYS.Global.Console.Y = Rows - 3;
            //    DimSH.Terminal.Write("              ", false);
            //    SYS.Global.Console.X = OutputCols;
            //    SYS.Global.Console.Y = Rows - 2;
            //    DimSH.Terminal.Write("              ", false);
            //    ClearStat();
            //    SYS.Global.Console.X = posX;
            //    SYS.Global.Console.Y = posY;
            //    Console.BackgroundColor = color;
            //    Interface.DrawSections();
            //    //return text;
            //}
            //return result;

        }

        //Trims the starting and trailing spaces from the string
        public static string Trim(string text, char splitter = ' ')
        {
            var result = text;
            var length = text.Length;
            if (length != 0)
            {
                var trimmingLength = 0;
                for (int i = 0; i < length; i++)
                {
                    if (text[i] == splitter) trimmingLength++;
                    else break;
                }
                result = result.Remove(0, trimmingLength);
                trimmingLength = 0;
                if (result.Length != 0)
                {
                    for (int i = length - 1; i >= 0; i--)
                    {
                        if (text[i] == splitter) trimmingLength++;
                        else break;
                    }
                    result = result.Remove(result.Length - trimmingLength, trimmingLength);
                }
            }
            return result;
        }

        public static string TrimStart(string text, char splitter = ' ')
        {
            var result = text;
            var length = text.Length;
            if (length != 0)
            {
                var trimmingLength = 0;
                for (int i = 0; i < length; i++)
                {
                    if (text[i] == splitter) trimmingLength++;
                    else break;
                }
                result = result.Remove(0, trimmingLength);
            }
            return result;
        }

        public static string TrimEnd(string text, char splitter = ' ')
        {
            var result = text;
            var length = text.Length;
            if (length != 0)
            {
                var trimmingLength = 0;
                if (result.Length != 0)
                {
                    for (int i = length - 1; i >= 0; i--)
                    {
                        if (text[i] == splitter) trimmingLength++;
                        else break;
                    }
                    result = result.Remove(result.Length - trimmingLength, trimmingLength);
                }
            }
            return result;
        }

        private static void Process(string command)
        {
            var commandLevels = command.Split('.');
            if (commandLevels[0] == "dim" || commandLevels[0] == "d")
            {
                if (commandLevels.Length == 1)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Red;
                    DimSH.Terminal.WriteLine("Not enough arguments!");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("Please issue \"");
                    Console.ForegroundColor = ConsoleColor.White;
                    DimSH.Terminal.Write("dim.?");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("\" command to view help.");
                    DimSH.Terminal.WriteLine();
                    Console.ForegroundColor = color;
                }
                else 
                {
                    string[] parameters = null;
                    if (commandLevels[1].IndexOf(' ') != -1)
                    {
                        parameters = commandLevels[1].Substring(commandLevels[1].IndexOf(' ') + 1).Split(' ');
                        commandLevels[1] = commandLevels[1].Substring(0, commandLevels[1].IndexOf(' '));
                    }
                    if (commandLevels[1] == "help" || commandLevels[1] == "h" || commandLevels[1] == "?")
                    {
                        var colorH = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.WriteLine("\"dim\" command provides an access to user applications.");
                        DimSH.Terminal.WriteLine("Available arguments:");
                        DimSH.Terminal.WriteLine();
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".c|.calc ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = provides mathematical and numeral systems' computing.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".s|.stopwatch ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = outputs every tick until it reaches stop number.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".t|.target ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = shows the list of all available Targets.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".q|.quiz ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = enters the Quiz-solving mode.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".g|.guess ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = enters the Guess-solving mode.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = colorH;
                    }
                    else if (commandLevels[1] == "calc" || commandLevels[1] == "c")
                    {
                        var colorC = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> <expression>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (parameters != null && parameters.Length != 0)
                            {
                                try
                                {
                                    string expr = "";
                                    // ReSharper disable once LoopCanBeConvertedToQuery
                                    // ReSharper disable once ForCanBeConvertedToForeach
                                    for (int i = 0; i < parameters.Length; i++) expr += parameters[i];
                                    DimSH.Terminal.WriteLine(new Calc().Evaluate(expr.ToUpper(), StringKey, StringValue));
                                    if (Calc.IndexOf(Targets[9], "....") != -1)
                                    {
                                        Targets[9] = Calc.Replace(Targets[9], "....", "DONE");
                                        _targets++;
                                    }
                                }
                                catch
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("Invalid syntax!");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Not enough parameters!");
                            }
                        }
                        Console.ForegroundColor = colorC;
                    }
                    else if (commandLevels[1] == "target" || commandLevels[1] == "t")
                    {
                        var colorP = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                // ReSharper disable once ForCanBeConvertedToForeach
                                // ReSharper disable once ForCanBeConvertedToForeach
                                for (int i = 0; i < Targets.Count; i++)
                                {
                                    DimSH.Terminal.Write(Targets[i].Substring(0, Targets[i].IndexOf('[')));
                                    Console.ForegroundColor = ConsoleColor.Gray;
                                    DimSH.Terminal.Write("[");
                                    var status = Targets[i].Substring(Targets[i].IndexOf('[') + 1,
                                        Targets[i].IndexOf(']') - Targets[i].IndexOf('[') - 1);
                                    if (status == "....") Console.ForegroundColor = ConsoleColor.Gray;
                                    else if (status.ToUpper() == "DONE") Console.ForegroundColor = ConsoleColor.Green;
                                    DimSH.Terminal.Write(status);
                                    Console.ForegroundColor = ConsoleColor.Gray;
                                    DimSH.Terminal.Write("]");
                                    DimSH.Terminal.WriteLine();
                                    SYS.Global.Console.X = 0;
                                    Console.ForegroundColor = colorP;
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorP;
                    }
                    else if (commandLevels[1] == "quiz" || commandLevels[1] == "q")
                    {
                        var colorQ = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                // ReSharper disable once ForCanBeConvertedToForeach
                                // ReSharper disable once ForCanBeConvertedToForeach
                                Console.ForegroundColor = ConsoleColor.DarkYellow;
                                Split();
                                Console.ForegroundColor = ConsoleColor.White;
                                if (_quizzes == Quizzes.Count)
                                {
                                    DimSH.Terminal.WriteLine("You have completed all Quizzes!");
                                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                                    Split();
                                    Console.ForegroundColor = ConsoleColor.White;
                                }
                                for (int i = 0; i < Quizzes.Count; i++)
                                {
                                    var check =
                                        Trim(Quizzes[i].Substring(Quizzes[i].IndexOf('[') + 1,
                                            Quizzes[i].IndexOf(']') - Quizzes[i].IndexOf('[') - 1));
                                    if (check != "")
                                    {
                                        var options = Quizzes[i].Substring(0, Quizzes[i].IndexOf('[')).Split('|');
                                        // ReSharper disable once ForCanBeConvertedToForeach
                                        DimSH.Terminal.WriteLine(options[0]);
                                        DimSH.Terminal.WriteLine();
                                        for (int j = 1; j < options.Length; j++) DimSH.Terminal.WriteLine(options[j]);
                                        SYS.Global.Console.X = 0;
                                        var answer = check.Split('|');
                                        var input = Trim(ReadLine());
                                        if (input == "exit")
                                        {
                                            Console.ForegroundColor = ConsoleColor.DarkYellow;
                                            Split();
                                            Console.ForegroundColor = ConsoleColor.White;
                                            break;
                                        }
                                        if (input != "skip" && input != "next")
                                        {
                                            var correct = false;
                                            // ReSharper disable once LoopCanBeConvertedToQuery
                                            // ReSharper disable ForCanBeConvertedToForeach
                                            for (int j = 0; j < answer.Length; j++)
                                                if (answer[j] == input)
                                                {
                                                    correct = true;
                                                    Quizzes[i] = Calc.Replace(Quizzes[i], check, string.Empty);
                                                    _quizzes++;
                                                    break;
                                                }
                                            // ReSharper restore ForCanBeConvertedToForeach
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Your answer [");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(input);
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("] is ");
                                            if (correct)
                                            {
                                                Console.ForegroundColor = ConsoleColor.Green;
                                                DimSH.Terminal.Write("correct");
                                            }
                                            else
                                            {
                                                Console.ForegroundColor = ConsoleColor.Red;
                                                DimSH.Terminal.Write("incorrect");
                                                i--;
                                            }
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("!");
                                            DimSH.Terminal.WriteLine();
                                        }
                                        Console.ForegroundColor = ConsoleColor.DarkYellow;
                                        Split();
                                        Console.ForegroundColor = ConsoleColor.White;
                                    }
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorQ;
                    }
                    else if (commandLevels[1] == "guess" || commandLevels[1] == "g")
                    {
                        var colorG = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                // ReSharper disable once ForCanBeConvertedToForeach
                                // ReSharper disable once ForCanBeConvertedToForeach
                                Console.ForegroundColor = ConsoleColor.DarkYellow;
                                Split();
                                Console.ForegroundColor = ConsoleColor.White;
                                if (_guesses == Guesses.Count)
                                {
                                    DimSH.Terminal.WriteLine("You have completed all Guesses!");
                                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                                    Split();
                                    Console.ForegroundColor = ConsoleColor.White;
                                }
                                for (int i = 0; i < Guesses.Count; i++)
                                {
                                    var check =
                                        Trim(Guesses[i].Substring(Guesses[i].IndexOf('[') + 1,
                                            Guesses[i].IndexOf(']') - Guesses[i].IndexOf('[') - 1));
                                    if (check != "")
                                    {
                                        DimSH.Terminal.WriteLine(Guesses[i].Substring(0, Guesses[i].IndexOf('[')));
                                        SYS.Global.Console.X = 0;
                                        var answer = check.Split('|');
                                        var input = Trim(ReadLine());
                                        if (input == "exit")
                                        {
                                            Console.ForegroundColor = ConsoleColor.DarkYellow;
                                            Split();
                                            Console.ForegroundColor = ConsoleColor.White;
                                            break;
                                        }
                                        if (input != "skip" && input != "next")
                                        {
                                            var correct = false;
                                            // ReSharper disable once LoopCanBeConvertedToQuery
                                            // ReSharper disable ForCanBeConvertedToForeach
                                            for (int j = 0; j < answer.Length; j++)
                                                if (answer[j] == input)
                                                {
                                                    correct = true;
                                                    Guesses[i] = Calc.Replace(Guesses[i], check, string.Empty);
                                                    _guesses++;
                                                    break;
                                                }
                                            // ReSharper restore ForCanBeConvertedToForeach
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Your answer [");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(input);
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("] is ");
                                            if (correct)
                                            {
                                                Console.ForegroundColor = ConsoleColor.Green;
                                                DimSH.Terminal.Write("correct");
                                            }
                                            else
                                            {
                                                Console.ForegroundColor = ConsoleColor.Red;
                                                DimSH.Terminal.Write("incorrect");
                                                i--;
                                            }
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("!");
                                            DimSH.Terminal.WriteLine();
                                        }
                                        Console.ForegroundColor = ConsoleColor.DarkYellow;
                                        Split();
                                        Console.ForegroundColor = ConsoleColor.White;
                                    }
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorG;
                    }
                    else if (commandLevels[1] == "stopwatch" || commandLevels[1] == "s")
                    {
                        var colorS = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> <number of ticks to stop>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (parameters != null && parameters.Length != 0)
                            {
                                try
                                {
                                    string stop = "";
                                    // ReSharper disable once LoopCanBeConvertedToQuery
                                    // ReSharper disable once ForCanBeConvertedToForeach
                                    for (int i = 0; i < parameters.Length; i++) stop += parameters[i] + " ";
                                    stop = Trim(stop.Remove(stop.Length - 1, 1));
                                    if (stop.IndexOf(' ') != -1) stop = stop.Substring(0, stop.IndexOf(' '));
                                    if (stop == "")
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Not enough parameters!");
                                    }
                                    else
                                    {
                                        if (Calc.IndexOf(Targets[10], "....") != -1 && stop == "10")
                                        {
                                            Targets[10] = Calc.Replace(Targets[10], "....", "DONE");
                                            _targets++;
                                        }
                                        for (int i = 1; i <= Calc.StringToInt(stop); i++)
                                        {
                                            Terminal.Wait(1);
                                            DimSH.Terminal.WriteLine("Tick: " + i);
                                        }
                                    }
                                }
                                catch
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("Invalid syntax!");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Not enough parameters!");
                            }
                        }
                        Console.ForegroundColor = colorS;
                    }
                        else if (commandLevels[1] == "expression")
                        {
                            string expr = "";
                            // ReSharper disable once LoopCanBeConvertedToQuery
                            // ReSharper disable once ForCanBeConvertedToForeach
                            for (int i = 0; i < parameters.Length; i++) expr += parameters[i];
                            DimSH.Terminal.WriteLine(new Calc().Evaluate(expr.ToUpper(), StringKey, StringValue));
                        }
                        else
                        {
                            var colorDef = Console.ForegroundColor;
                            Console.ForegroundColor = ConsoleColor.Red;
                            DimSH.Terminal.WriteLine("Wrong argument!");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Please issue \"");
                            Console.ForegroundColor = ConsoleColor.White;
                            DimSH.Terminal.Write("dim.?");
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("\" command to view help.");
                            DimSH.Terminal.WriteLine();
                            Console.ForegroundColor = colorDef;
                        }
                }
            }
            else if (commandLevels[0] == "set" || commandLevels[0] == "s")
            {
                if (commandLevels.Length == 1)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Red;
                    DimSH.Terminal.WriteLine("Not enough arguments!");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("Please issue \"");
                    Console.ForegroundColor = ConsoleColor.White;
                    DimSH.Terminal.Write("set.?");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("\" command to view help.");
                    DimSH.Terminal.WriteLine();
                    Console.ForegroundColor = color;
                }
                else
                {
                    string[] parameters = null;
                    if (commandLevels[1].IndexOf(' ') != -1)
                    {
                        parameters = commandLevels[1].Substring(commandLevels[1].IndexOf(' ') + 1).Split(' ');
                        commandLevels[1] = commandLevels[1].Substring(0, commandLevels[1].IndexOf(' '));
                    }
                    if (commandLevels[1] == "help" || commandLevels[1] == "h" || commandLevels[1] == "?")
                    {
                        var colorH = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.WriteLine("\"set\" command provides DimSH.Terminal.Write access to shell's resources.");
                        DimSH.Terminal.WriteLine("Available arguments:");
                        DimSH.Terminal.WriteLine();
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".s|.string ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = DimSH.Terminal.Writes a string to the string buffer (root).");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".r|.root ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = switches the shell to the root-access mode.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".u|.user ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = switches the shell to the user-access mode.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".p|.password ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = sets the root-access password (root).");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".d|.dim ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = sets the user-access dim (prompt).");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = colorH;
                    }
                    else if (commandLevels[1] == "variable" || commandLevels[1] == "v")
                    {
                        var colorS = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> <string name>(<parameters>) [\"|{]<body>[}|\"]");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (_root)
                            {
                                if (parameters != null && parameters.Length != 0)
                                {
                                    try
                                    {
                                        string str = "";
                                        // ReSharper disable once LoopCanBeConvertedToQuery
                                        // ReSharper disable once ForCanBeConvertedToForeach
                                        for (int i = 0; i < parameters.Length; i++) str += parameters[i] + " ";
                                        str = str.Remove(str.Length - 1, 1);
                                        string key = "", value;
                                        if (str.IndexOf('"') != - 1)
                                        {
                                            var keySpaces = str.Substring(0, str.IndexOf('"')).ToUpper();
                                            // ReSharper disable once LoopCanBeConvertedToQuery
                                            // ReSharper disable once ForCanBeConvertedToForeach
                                            for (int i = 0; i < keySpaces.Length; i++)
                                                if (keySpaces[i] != ' ' && keySpaces[i] != '+' && keySpaces[i] != '-' &&
                                                    keySpaces[i] != '/' && keySpaces[i] != '*' && keySpaces[i] != '%' &&
                                                    keySpaces[i] != '^' && keySpaces[i] != '(' && keySpaces[i] != ')' &&
                                                    keySpaces[i] != '|' && keySpaces[i] != '#' && keySpaces[i] != '<' &&
                                                    keySpaces[i] != '>' && keySpaces[i] != '=' && keySpaces[i] != '$')
                                                    key += keySpaces[i];
                                            if (key.IndexOf('[') == -1 && key.IndexOf(']') == -1) key += "[]";
                                            else if (key.IndexOf('[') != -1 && key.IndexOf(']') == -1) key += "]";
                                            else if (key.IndexOf(']') != -1 && key.IndexOf('[') == -1)
                                                key = key.Insert(key.IndexOf(']'), "[");
                                            str = str.Remove(0, str.IndexOf('"') + 1);
                                            value = Trim(str.Substring(0, str.IndexOf('"')));
                                            var trigger = false;
                                            for (int i = 0; i < StringKey.Length; i++)
                                                if (key.Substring(0, key.IndexOf('[')) ==
                                                    StringKey[i].Substring(0, StringKey[i].IndexOf('[')))
                                                {
                                                    StringKey[i] = key;
                                                    StringValue[i] = value;
                                                    trigger = true;
                                                    break;
                                                }
                                            if (!trigger)
                                            {
                                                if (_index <= StringKey.Length)
                                                {
                                                    StringKey[_index] = key;
                                                    StringValue[_index] = value;
                                                    _index++;
                                                }
                                                else
                                                {
                                                    Console.ForegroundColor = ConsoleColor.Red;
                                                    DimSH.Terminal.WriteLine("String buffer overflow!");
                                                    key = "Error";
                                                    value = "Error";
                                                }
                                            }
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Key: ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(key);
                                            DimSH.Terminal.WriteLine();
                                            SYS.Global.Console.X = 0;
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Value: ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(value);
                                            DimSH.Terminal.WriteLine();
                                            if (Calc.IndexOf(Targets[3], "....") != -1)
                                            {
                                                Targets[3] = Calc.Replace(Targets[3], "....", "DONE");
                                                _targets++;
                                            }
                                        }
                                        else if (str.IndexOf('{') != - 1 && str.IndexOf('}') != -1)
                                        {
                                            var keySpaces = str.Substring(0, str.IndexOf('{')).ToUpper();
                                            // ReSharper disable once LoopCanBeConvertedToQuery
                                            // ReSharper disable once ForCanBeConvertedToForeach
                                            for (int i = 0; i < keySpaces.Length; i++)
                                                if (keySpaces[i] != ' ' && keySpaces[i] != '+' && keySpaces[i] != '-' &&
                                                    keySpaces[i] != '/' && keySpaces[i] != '*' && keySpaces[i] != '%' &&
                                                    keySpaces[i] != '^' && keySpaces[i] != '(' && keySpaces[i] != ')' &&
                                                    keySpaces[i] != '|' && keySpaces[i] != '#' && keySpaces[i] != '<' &&
                                                    keySpaces[i] != '>' && keySpaces[i] != '=' && keySpaces[i] != '$')
                                                    key += keySpaces[i];
                                            if (key.IndexOf('[') == -1 && key.IndexOf(']') == -1) key += "[]";
                                            else if (key.IndexOf('[') != -1 && key.IndexOf(']') == -1) key += "]";
                                            else if (key.IndexOf(']') != -1 && key.IndexOf('[') == -1)
                                                key = key.Insert(key.IndexOf(']'), "[");
                                            str = str.Remove(0, str.IndexOf('{') + 1);
                                            value = Trim(str.Substring(0, str.IndexOf('}')));
                                            var trigger = false;
                                            for (int i = 0; i < StringKey.Length; i++)
                                                if (key.Substring(0, key.IndexOf('[')) ==
                                                    StringKey[i].Substring(0, StringKey[i].IndexOf('[')))
                                                {
                                                    StringKey[i] = key;
                                                    StringValue[i] = value;
                                                    trigger = true;
                                                    break;
                                                }
                                            if (!trigger)
                                            {
                                                if (_index <= StringKey.Length)
                                                {
                                                    StringKey[_index] = key;
                                                    StringValue[_index] = value;
                                                    _index++;
                                                }
                                                else
                                                {
                                                    Console.ForegroundColor = ConsoleColor.Red;
                                                    DimSH.Terminal.WriteLine("String buffer overflow!");
                                                    key = "Error";
                                                    value = "Error";
                                                }
                                            }
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Key: ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(key);
                                            DimSH.Terminal.WriteLine();
                                            SYS.Global.Console.X = 0;
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("Value: ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(value);
                                            DimSH.Terminal.WriteLine();
                                            if (Calc.IndexOf(Targets[3], "....") != -1)
                                            {
                                                Targets[3] = Calc.Replace(Targets[3], "....", "DONE");
                                                _targets++;
                                            }
                                        }
                                        else
                                        {
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            DimSH.Terminal.WriteLine("Not enough parameters!");
                                        }
                                    }
                                    catch
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Invalid syntax!");
                                    }
                                }
                                else
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("Not enough parameters!");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("You do not have sufficient privileges!");
                            }
                        }
                        Console.ForegroundColor = colorS;
                    }
                    else if (commandLevels[1] == "root" || commandLevels[1] == "r")
                    {
                        var colorR = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> (<password>)");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (_root)
                            {
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.WriteLine("You are already in the root-access mode.");
                            }
                            else
                            {
                                if (parameters != null && parameters.Length != 0)
                                {
                                    try
                                    {
                                        string password = "";
                                        // ReSharper disable once LoopCanBeConvertedToQuery
                                        // ReSharper disable once ForCanBeConvertedToForeach
                                        for (int i = 0; i < parameters.Length; i++) password += parameters[i] + " ";
                                        password = Trim(password.Remove(password.Length - 1, 1));
                                        if (password.IndexOf(' ') != -1)
                                            password = password.Substring(0, password.IndexOf(' '));
                                        if (_password != "" && password == "")
                                        {
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.WriteLine("Please retype the command with the password specified!");
                                        }
                                        else if (_password == password || _password == "")
                                        {
                                            _root = true;
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.WriteLine("Switched to root-access mode.");
                                            if (_password == "")
                                            {
                                                Console.ForegroundColor = ConsoleColor.Gray;
                                                DimSH.Terminal.WriteLine("Warning: root-access password is not set!");
                                            }
                                            if (Calc.IndexOf(Targets[1], "....") != -1)
                                            {
                                                Targets[1] = Calc.Replace(Targets[1], "....", "DONE");
                                                _targets++;
                                            }
                                        }
                                        else
                                        {
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            DimSH.Terminal.WriteLine("Invalid password!");
                                        }
                                    }
                                    catch
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Invalid syntax!");
                                    }
                                }
                                else
                                {
                                    if (_password != "")
                                    {
                                        Console.ForegroundColor = ConsoleColor.Gray;
                                        DimSH.Terminal.WriteLine("Please retype the command with the password specified!");
                                    }
                                    else
                                    {
                                        _root = true;
                                        Console.ForegroundColor = ConsoleColor.Gray;
                                        DimSH.Terminal.WriteLine("Switched to root-access mode.");
                                        DimSH.Terminal.WriteLine("Warning: root-access password is not set!");
                                        if (Calc.IndexOf(Targets[1], "....") != -1)
                                        {
                                            Targets[1] = Calc.Replace(Targets[1], "....", "DONE");
                                            _targets++;
                                        }
                                    }
                                }
                            }
                        }
                        Console.ForegroundColor = colorR;
                    }
                    else if (commandLevels[1] == "user" || commandLevels[1] == "u")
                    {
                        var colorU = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (!_root)
                            {
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.WriteLine("You are already in the user-access mode.");
                            }
                            else
                            {
                                _root = false;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.WriteLine("Switched to user-access mode.");
                                if (Calc.IndexOf(Targets[4], "....") != -1)
                                {
                                    Targets[4] = Calc.Replace(Targets[4], "....", "DONE");
                                    _targets++;
                                }
                            }
                        }
                        Console.ForegroundColor = colorU;
                    }
                    else if (commandLevels[1] == "password" || commandLevels[1] == "p")
                    {
                        var colorP = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> (<password>)");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (_root)
                            {
                                if (parameters != null && parameters.Length != 0)
                                {
                                    try
                                    {
                                        string password = "";
                                        // ReSharper disable once LoopCanBeConvertedToQuery
                                        // ReSharper disable once ForCanBeConvertedToForeach
                                        for (int i = 0; i < parameters.Length; i++) password += parameters[i] + " ";
                                        password = Trim(password.Remove(password.Length - 1, 1));
                                        if (password.IndexOf(' ') != -1)
                                            password = password.Substring(0, password.IndexOf(' '));
                                        if (password == "")
                                        {
                                            _password = "";
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.WriteLine("Root-access password successfully cleared.");
                                        }
                                        else
                                        {
                                            _password = password;
                                            Console.ForegroundColor = ConsoleColor.Gray;
                                            DimSH.Terminal.Write("New root-access password: ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(_password);
                                            DimSH.Terminal.WriteLine();
                                            if (Calc.IndexOf(Targets[2], "....") != -1)
                                            {
                                                Targets[2] = Calc.Replace(Targets[2], "....", "DONE");
                                                _targets++;
                                            }
                                        }
                                    }
                                    catch
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Invalid syntax!");
                                    }
                                }
                                else
                                {
                                    _password = "";
                                    Console.ForegroundColor = ConsoleColor.Gray;
                                    DimSH.Terminal.WriteLine("Root-access password successfully cleared.");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("You do not have sufficient privileges!");
                            }
                        }
                        Console.ForegroundColor = colorP;
                    }
                    else if (commandLevels[1] == "dim" || commandLevels[1] == "d")
                    {
                        var colorD = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> <prompt>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (parameters != null && parameters.Length != 0)
                            {
                                try
                                {
                                    string prompt = "";
                                    // ReSharper disable once LoopCanBeConvertedToQuery
                                    // ReSharper disable once ForCanBeConvertedToForeach
                                    for (int i = 0; i < parameters.Length; i++) prompt += parameters[i] + " ";
                                    prompt = Trim(prompt.Remove(prompt.Length - 1, 1));
                                    if (prompt.IndexOf(' ') != -1)
                                        prompt = prompt.Substring(0, prompt.IndexOf(' '));
                                    if (prompt == "")
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Not enough parameters!");
                                    }
                                    else
                                    {
                                        _prompt = prompt;
                                        Console.ForegroundColor = ConsoleColor.Gray;
                                        DimSH.Terminal.Write("Successguly changed prompt to: ");
                                        Console.ForegroundColor = ConsoleColor.White;
                                        DimSH.Terminal.Write(_prompt);
                                        DimSH.Terminal.WriteLine();
                                        if (Calc.IndexOf(Targets[0], "....") != -1)
                                        {
                                            Targets[0] = Calc.Replace(Targets[0], "....", "DONE");
                                            _targets++;
                                        }
                                    }
                                }
                                catch
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("Invalid syntax!");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Not enough parameters!");
                            }
                        }
                        Console.ForegroundColor = colorD;
                    }
                    else
                    {
                        var colorDef = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Red;
                        DimSH.Terminal.WriteLine("Wrong argument!");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.Write("Please issue \"");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write("set.?");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.Write("\" command to view help.");
                        DimSH.Terminal.WriteLine();
                        Console.ForegroundColor = colorDef;
                    }
                }
            }
            else if (commandLevels[0] == "get" || commandLevels[0] == "g")
            {
                if (commandLevels.Length == 1)
                {
                    var color = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Red;
                    DimSH.Terminal.WriteLine("Not enough arguments!");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("Please issue \"");
                    Console.ForegroundColor = ConsoleColor.White;
                    DimSH.Terminal.Write("get.?");
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.Write("\" command to view help.");
                    DimSH.Terminal.WriteLine();
                    Console.ForegroundColor = color;
                }
                else
                {
                    string[] parameters = null;
                    if (commandLevels[1].IndexOf(' ') != -1)
                    {
                        parameters = commandLevels[1].Substring(commandLevels[1].IndexOf(' ') + 1).Split(' ');
                        commandLevels[1] = commandLevels[1].Substring(0, commandLevels[1].IndexOf(' '));
                    }
                    if (commandLevels[1] == "help" || commandLevels[1] == "h" || commandLevels[1] == "?")
                    {
                        var colorH = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.WriteLine("\"get\" command provides read access to shell's resources.");
                        DimSH.Terminal.WriteLine("Available arguments:");
                        DimSH.Terminal.WriteLine();
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".s|.string ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = reads a string from the string buffer (root).");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".p|.password ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = shows current root-access password (root).");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".f|.fact ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = shows the next fact about Operating Systems.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".i|.info ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = outputs the information about Operating System.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = ConsoleColor.DarkGreen;
                        DimSH.Terminal.Write(".b|.beep ");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write(" = produces a beeping sound.");
                        DimSH.Terminal.WriteLine();
                        SYS.Global.Console.X = 0;
                        Console.ForegroundColor = colorH;
                    }
                    else if (commandLevels[1] == "string" || commandLevels[1] == "s")
                    {
                        var colorS = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command> <string name>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            if (_root)
                            {
                                if (parameters != null && parameters.Length != 0)
                                {
                                    try
                                    {
                                        string key = "";
                                        // ReSharper disable once LoopCanBeConvertedToQuery
                                        // ReSharper disable once ForCanBeConvertedToForeach
                                        for (int i = 0; i < parameters.Length; i++) key += parameters[i];
                                        key = key.ToUpper();
                                        if (key.IndexOf('[') != -1) key = key.Substring(0, key.IndexOf('['));
                                        if (key.IndexOf(']') != -1) key = key.Substring(0, key.IndexOf(']'));
                                        var trigger = false;
                                        for (int i = 0; i < StringKey.Length; i++)
                                        {
                                            if (key == StringKey[i].Substring(0, StringKey[i].IndexOf('[')))
                                            {
                                                Console.ForegroundColor = ConsoleColor.Gray;
                                                DimSH.Terminal.Write("Key: ");
                                                Console.ForegroundColor = ConsoleColor.White;
                                                DimSH.Terminal.Write(StringKey[i]);
                                                DimSH.Terminal.WriteLine();
                                                SYS.Global.Console.X = 0;
                                                Console.ForegroundColor = ConsoleColor.Gray;
                                                DimSH.Terminal.Write("Value: ");
                                                Console.ForegroundColor = ConsoleColor.White;
                                                DimSH.Terminal.Write(StringValue[i]);
                                                DimSH.Terminal.WriteLine();
                                                trigger = true;
                                                if (Calc.IndexOf(Targets[8], "....") != -1)
                                                {
                                                    Targets[8] = Calc.Replace(Targets[8], "....", "DONE");
                                                    _targets++;
                                                }
                                                break;
                                            }
                                        }
                                        if (!trigger)
                                        {
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            DimSH.Terminal.Write("String ");
                                            Console.ForegroundColor = ConsoleColor.White;
                                            DimSH.Terminal.Write(key + " ");
                                            Console.ForegroundColor = ConsoleColor.Red;
                                            DimSH.Terminal.Write("not found!");
                                            DimSH.Terminal.WriteLine();
                                        }
                                    }
                                    catch
                                    {
                                        Console.ForegroundColor = ConsoleColor.Red;
                                        DimSH.Terminal.WriteLine("Invalid syntax!");
                                    }
                                }
                                else
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("Not enough parameters!");
                                }
                            }
                            else
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("You do not have sufficient privileges!");
                            }
                        }
                        Console.ForegroundColor = colorS;
                    }
                    else if (commandLevels[1] == "fact" || commandLevels[1] == "f")
                    {
                        var colorF = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                if (_factsIndex == Facts.Count - 1) _factsIndex = 0;
                                DimSH.Terminal.WriteLine(Facts[_factsIndex]);
                                _factsIndex++;
                                if (Calc.IndexOf(Targets[6], "....") != -1)
                                {
                                    Targets[6] = Calc.Replace(Targets[6], "....", "DONE");
                                    _targets++;
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorF;
                    }
                    else if (commandLevels[1] == "password" || commandLevels[1] == "p")
                    {
                        var colorP = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                if (_root)
                                {
                                    if (_password != "")
                                    {
                                        Console.ForegroundColor = ConsoleColor.Gray;
                                        DimSH.Terminal.Write("Root-access password: ");
                                        Console.ForegroundColor = ConsoleColor.White;
                                        DimSH.Terminal.Write(_password);
                                        DimSH.Terminal.WriteLine();
                                    }
                                    else
                                    {
                                        Console.ForegroundColor = ConsoleColor.Gray;
                                        DimSH.Terminal.WriteLine("No password curretly set for root-access mode.");
                                    }
                                    if (Calc.IndexOf(Targets[7], "....") != -1)
                                    {
                                        Targets[7] = Calc.Replace(Targets[7], "....", "DONE");
                                        _targets++;
                                    }
                                }
                                else
                                {
                                    Console.ForegroundColor = ConsoleColor.Red;
                                    DimSH.Terminal.WriteLine("You do not have sufficient privileges!");
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorP;
                    }
                    else if (commandLevels[1] == "beep" || commandLevels[1] == "b")
                    {
                        var colorP = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                DimSH.Terminal.WriteLine("Beeeeeeeeeeeeeeeeeeeeeeeeep!!!");
                                // ReSharper disable once ConvertToConstant.Local
                                uint divA = 1193180/1000;
                                CORE.BaseIOGroups.PCSpeaker.p43.Byte = 0xB6;
                                CORE.BaseIOGroups.PCSpeaker.p42.Byte = (byte) divA;
                                CORE.BaseIOGroups.PCSpeaker.p42.Byte = (byte) (divA >> 8);
                                ushort tempA = CORE.BaseIOGroups.PCSpeaker.p61.Byte;
                                if (tempA != (tempA | 3)) CORE.BaseIOGroups.PCSpeaker.p61.Byte = (byte) (tempA | 3);
                                // ReSharper disable once ConvertToConstant.Local
                                UInt32 divB = 1193180;
                                CORE.BaseIOGroups.PCSpeaker.p42.Byte = (byte) divB;
                                Terminal.Wait(1);
                                // ReSharper disable once SuggestUseVarKeywordEvident
                                byte tempB = (byte) (CORE.BaseIOGroups.PCSpeaker.p61.Byte & 0xFC);
                                CORE.BaseIOGroups.PCSpeaker.p61.Byte = tempB;
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorP;
                    }
                    else if (commandLevels[1] == "info" || commandLevels[1] == "i")
                    {
                        var colorI = Console.ForegroundColor;
                        if (commandLevels[2] == "help" || commandLevels[2] == "h" || commandLevels[2] == "?")
                        {
                            Console.ForegroundColor = ConsoleColor.Gray;
                            DimSH.Terminal.Write("Usage format: ");
                            Console.ForegroundColor = ConsoleColor.DarkGreen;
                            DimSH.Terminal.Write("<command>");
                            DimSH.Terminal.WriteLine();
                            SYS.Global.Console.X = 0;
                        }
                        else
                        {
                            try
                            {
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("TextScreen Size: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write(Cols + "x" + Rows);
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("DimOS Version: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write(Version);
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("Ownership: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write("Mikkeli University of Applied Sciences");
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("Developers: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write("Galakhov Daniil & Aktore Beket");
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("Source language: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write("C#");
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                Console.ForegroundColor = ConsoleColor.Gray;
                                DimSH.Terminal.Write("String buffer size: ");
                                Console.ForegroundColor = ConsoleColor.White;
                                DimSH.Terminal.Write(StringKey.Length.ToString());
                                DimSH.Terminal.WriteLine();
                                SYS.Global.Console.X = 0;
                                if (Calc.IndexOf(Targets[5], "....") != -1)
                                {
                                    Targets[5] = Calc.Replace(Targets[5], "....", "DONE");
                                    _targets++;
                                }
                            }
                            catch
                            {
                                Console.ForegroundColor = ConsoleColor.Red;
                                DimSH.Terminal.WriteLine("Unknown error!");
                            }
                        }
                        Console.ForegroundColor = colorI;
                    }
                    else
                    {
                        var colorDef = Console.ForegroundColor;
                        Console.ForegroundColor = ConsoleColor.Red;
                        DimSH.Terminal.WriteLine("Wrong argument!");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.Write("Please issue \"");
                        Console.ForegroundColor = ConsoleColor.White;
                        DimSH.Terminal.Write("get.?");
                        Console.ForegroundColor = ConsoleColor.Gray;
                        DimSH.Terminal.Write("\" command to view help.");
                        DimSH.Terminal.WriteLine();
                        Console.ForegroundColor = colorDef;
                    }
                }
            }
            else if (commandLevels[0] == "cls")
            {
                if (commandLevels[1] == "help" || commandLevels[1] == "h" || commandLevels[1] == "?")
                {
                    var colorH = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Gray;
                    DimSH.Terminal.WriteLine("\"cls\" clears the output section.");
                    Console.ForegroundColor = colorH;
                }
                else
                {
                    for (int i = 0; i < Rows - 2; i++) DimSH.Terminal.WriteLine();
                    if (Calc.IndexOf(Targets[11], "....") != -1)
                    {
                        Targets[11] = Calc.Replace(Targets[11], "....", "DONE");
                        _targets++;
                    }
                }
            }
            else
            {
                var color = Console.ForegroundColor;
                Console.ForegroundColor = ConsoleColor.Red;
                DimSH.Terminal.WriteLine("Unknown command!");
                Console.ForegroundColor = ConsoleColor.Gray;
                DimSH.Terminal.Write("Please issue \"");
                Console.ForegroundColor = ConsoleColor.White;
                DimSH.Terminal.Write("?");
                Console.ForegroundColor = ConsoleColor.Gray;
                DimSH.Terminal.Write("\" command to view help.");
                DimSH.Terminal.WriteLine();
                Console.ForegroundColor = color;
            }
        }

    }

    //Class for calculating mathematical expressions
    class Calc
    {
        enum Types { None, Delimiter, Number }; //Token types
        string _expr; //Variable for storing the mathematical expression
        int _exprId; //Variable for storing current index in the expression
        string _token; //Variable for storing current token
        Types _tokenType; //Variable for storing current token's type
        string[] _functionKey;
        string[] _functionValue;

        //Method for calculating given mathematical expression
        public string Evaluate(string expression, string[] functionKey = null, string[] functionValue = null)
        {
            //var resultNumbase = "";
            //var cell = "";
            //var rep = "";
            //var hexRep = "";
            //var memCell = "";
            //var isNegative = false;
            //var isPositive = false;
            //_functionKey = functionKey;
            //_functionValue = functionValue;
            //_expr = expression;
            //_exprId = 0;
            //if (_expr.IndexOf('=') != -1)
            //{
            //    resultNumbase = Kernel.Trim(_expr.Split('=')[1]);
            //    _expr = Kernel.Trim(_expr.Split('=')[0]);
            //}
            //if (resultNumbase.IndexOf('$') != -1)
            //{
            //    cell = Kernel.Trim(resultNumbase.Split('$')[1]);
            //    resultNumbase = Kernel.Trim(resultNumbase.Split('$')[0]);
            //    if (resultNumbase.IndexOf('|') != -1) resultNumbase = Kernel.Trim(resultNumbase.Split('|')[0]);
            //    if (resultNumbase.IndexOf('#') != -1) resultNumbase = Kernel.Trim(resultNumbase.Split('#')[0]);
            //    if (cell.IndexOf('|') != -1)
            //    {
            //        rep = Kernel.Trim(cell.Split('|')[1]);
            //        cell = Kernel.Trim(cell.Split('|')[0]);
            //    }
            //}
            //if (_expr.IndexOf('#') != -1 && resultNumbase == "" && cell == "")
            //{
            //    hexRep = _expr.Split('#')[0];
            //    if (_expr.IndexOf('|') != -1) _expr = Kernel.Trim(_expr.Split('|')[0]);
            //    if (_expr.IndexOf('$') != -1) _expr = Kernel.Trim(_expr.Split('$')[0]);
            //}
            //if (hexRep == "" && resultNumbase == "" && cell == "" && (_expr.IndexOf('<') != -1 || _expr.IndexOf('>') != -1))
            //{
            //    if (_expr.IndexOf('<') != -1) isNegative = true;
            //    if (_expr.IndexOf('>') != -1) isPositive = true;
            //    memCell = Kernel.Trim(Replace(Replace(_expr, ">", string.Empty), "<", string.Empty));
            //}

            //try
            //{
                float result = 0;
                //if (hexRep == "" && memCell == "")
                //{
                    GetToken();
                    if (_token == "")
                    {
                        return "0";
                    }
                    EvalSum(out result);
            return result.ToString();
            //}
            //    if (resultNumbase != "" || cell != "" || hexRep != "" || memCell != "")
            //    {
            //        string final;
            //        if (cell != "")
            //        {
            //            if (rep != "")
            //            {
            //                if (result.ToString().IndexOf('.') != -1 || result.ToString().IndexOf(',') != -1)
            //                    final = ComputerNumbers.FloatToComp(result.ToString(), 10, StringToInt(cell), StringToInt(rep));
            //                else final = ComputerNumbers.IntToComp(result.ToString(), 10, StringToInt(cell), StringToInt(rep));
            //            }
            //            else
            //            {
            //                if (result.ToString().IndexOf('.') != -1 || result.ToString().IndexOf(',') != -1)
            //                    final = ComputerNumbers.FloatToComp(result.ToString(), 10, StringToInt(cell));
            //                else final = ComputerNumbers.IntToComp(result.ToString(), 10, StringToInt(cell));
            //            }
            //        }
            //        else if (resultNumbase != "")
            //        {
            //            if (result.ToString().IndexOf('.') != -1 || result.ToString().IndexOf(',') != -1)
            //                final = ComputerNumbers.FloatToSys(result.ToString(), 10, StringToInt(resultNumbase));
            //            else final = ComputerNumbers.DecimalToBase(result.ToString(), StringToInt(resultNumbase));
            //        }
            //        else if (hexRep != "") final = ComputerNumbers.FromHexRep(hexRep, 10);
            //        else if (memCell != "") final = ComputerNumbers.RangeOfVariation(StringToInt(memCell), isNegative, isPositive);
            //        else final = "0";
            //        return final;
            //    }
            //    return result.ToString();
            //}
            //catch
            //{
            //    return "Error";
            //}
        }

        //Method for adding and substracting two numbers of the expression
        void EvalSum(out float result)
        {
            string op;
            EvalMul(out result);
            while ((op = _token) == "+" || op == "-" || op == ";")
            {
                GetToken();
                float partialResult;
                EvalMul(out partialResult);
                switch (op)
                {
                    case "-":
                        result = result - partialResult;
                        break;
                    case "+":
                        result = result + partialResult;
                        break;
                    case ";":
                        Console.Write(result);
                        Console.Write(" ; ");
                        Console.WriteLine(partialResult);
                        result = 1;
                        break;
                }
            }
        }

        //Method for multiplying and dividing two numbers of the expression
        void EvalMul(out float result)
        {
            string op;
            EvalPow(out result);
            while ((op = _token) == "*" || op == "/" || op == "%" || op == "=")
            {
                GetToken();
                float partialResult;
                EvalPow(out partialResult);
                switch (op)
                {
                    case "*":
                        result = result * partialResult;
                        break;
                    case "/":
                        result = result / partialResult;
                        break;
                    case "%":
                        result = result % partialResult;
                        break;
                    case "=":
                        Console.Write(result);
                        Console.Write(" = ");
                        Console.WriteLine(partialResult);
                        result = 1;
                        break;
                }
            }
        }

        //Method for exponentiating
        void EvalPow(out float result)
        {
            EvalUnary(out result);
            if (_token == "^")
            {
                GetToken();
                float partialResult;
                EvalPow(out partialResult);
                float ex = result;
                // ReSharper disable once CompareOfFloatsByEqualityOperator
                if (partialResult == 0.0)
                {
                    result = 1;
                    return;
                }
                int t;
                for (t = Convert.ToInt32(partialResult) - 1; t > 0; t--) result = result * ex;
            }
        }

        //Method for unary adding and subtracting
        void EvalUnary(out float result)
        {
            string op = "";
            if ((_tokenType == Types.Delimiter) && _token == "+" || _token == "-")
            {
                op = _token;
                GetToken();
            }
            EvalPar(out result);
            if (op == "-") result = -result;
        }

        //Method for evaluating the expression in parenthesis
        void EvalPar(out float result)
        {
            if ((_token == "(" || _token == "{"))
            {
                GetToken();
                EvalSum(out result);
                GetToken();
            }
            else Atom(out result);
        }

        //Method for retrieving the value of a number
        void Atom(out float result)
        {
            switch (_tokenType)
            {
                case Types.Number:
                    try
                    {
                        if (_token.IndexOf('[') != -1 && _token.IndexOf(']') != -1)
                        {
                            if (_functionKey != null && _functionValue != null)
                            {
                                var function = _token.Substring(0, _token.IndexOf('[')).ToUpper();
                                var parameters = _token.Substring(_token.IndexOf('[') + 1, _token.IndexOf(']') - _token.IndexOf('[') - 1).Split(':');
                                for (int i = 0; i < _functionKey.Length; i++)
                                {
                                    if (_functionKey[i].IndexOf('[') != -1 &&
                                        _functionKey[i].Substring(0, _functionKey[i].IndexOf('[')).ToUpper() == function)
                                    {
                                        var parametersKey =
                                            _functionKey[i].Substring(_functionKey[i].IndexOf('[') + 1,
                                                _functionKey[i].IndexOf(']') - _functionKey[i].IndexOf('[') - 1)
                                                .Split(':');
                                        if (parameters.Length == parametersKey.Length)
                                        {
                                            var functionValue = _functionValue[i];
                                            for (int j = 0; j < parameters.Length; j++)
                                            {
                                                functionValue = Replace(functionValue, parametersKey[j].ToLower(), parameters[j]);
                                                functionValue = Replace(functionValue, parametersKey[j].ToUpper(), parameters[j]);
                                            }
                                            _token = new Calc().Evaluate(functionValue);
                                        }
                                        else _token = "";
                                        break;
                                    }
                                }
                            }
                        }
                        if (_token.IndexOf('_') != -1)
                        {
                            if (_token.IndexOf('.') != -1 || _token.IndexOf(',') != -1)
                                _token = ComputerNumbers.FloatToSys(_token.Split('_')[0],
                                    StringToInt(_token.Split('_')[1]), 10);
                            else
                                _token = ComputerNumbers.BaseToDecimal(_token.Split('_')[0],
                                    StringToInt(_token.Split('_')[1]));
                        }
                        result = StringToFloat(_token);
                    }
                    catch (FormatException)
                    {
                        result = 0;
                    }
                    GetToken();
                    return;
                default:
                    result = 0;
                    break;
            }
        }

        //Method for retrieving the next token
        void GetToken()
        {
            _tokenType = Types.None;
            _token = "";
            if (_exprId == _expr.Length) return; //End of expression
            while (_exprId < _expr.Length && DimOS.Plugs.Char.IsWhiteSpace(_expr[_exprId])) ++_exprId; //Skipping spaces
            if (_exprId == _expr.Length) return; //Trailing space ends the expression
            if (IsDelim(_expr[_exprId])) //Checking if it is a statement
            {
                _token += _expr[_exprId];
                _exprId++;
                _tokenType = Types.Delimiter;
            }
            else if ("0123456789QWERTYUIOPASDFGHJKLZXCVBNM".IndexOf(_expr[_exprId]) != -1) //Checking if it is a number
            {
                while (!IsDelim(_expr[_exprId]))
                {
                    _token += _expr[_exprId];
                    _exprId++;
                    if (_exprId >= _expr.Length) break;
                }
                _tokenType = Types.Number;
            }
        }

        //Method for determining if a given character is a delimiter
        bool IsDelim(char c)
        {
            if ((" +-/*%^();={}".IndexOf(c) != -1)) return true;
            return false;
        }

        //Method for converting a string to float
        public static float StringToFloat(string expr)
        {
            int length = expr.Length, start = 0, f = 1, i;
            float result = 0;
            bool isNegative = false;
            bool isFloat = false;
            if (expr[0] == '-')
            {
                isNegative = true;
                start = 1;
            }
            else if (expr[0] == '+') start = 1;
            for (i = start; i < length; i++)
            {
                if (expr[i] == '.' || expr[i] == ',') isFloat = true;
                else if ((expr[i] >= '0') && expr[i] <= '9')
                {
                    if (i > 0) result *= 10;
                    result += expr[i] - '0';
                    if (isFloat) f *= 10;
                }
                else if (expr[i] != ' ') break;
            }
            if (isNegative) result *= -1;
            if (isFloat) result /= f;
            return result;
        }

        //Method for converting a string to Int32
        public static int StringToInt(string expr)
        {
            int length = expr.Length, start = 0, i;
            int result = 0;
            bool isNegative = false;
            if (expr[0] == '-')
            {
                isNegative = true;
                start = 1;
            }
            else if (expr[0] == '+') start = 1;
            for (i = start; i < length; i++)
            {
                if ((expr[i] >= '0') && expr[i] <= '9')
                {
                    if (i > 0) result *= 10;
                    result += expr[i] - '0';
                }
                else if (expr[i] != ' ') break;
            }
            if (isNegative) result *= -1;
            return result;
        }

        //Method for reversing a string
        public static string Reverse(string text)
        {
            char[] cArray = text.ToCharArray();
            string reverse = "";
            for (int i = cArray.Length - 1; i > -1; i--) reverse += cArray[i];
            return reverse;
        }

        //Method for retrieving position of substring in string
        public static int IndexOf(string text, string sub)
        {
            int result = -1;
            int index = 0;
            if (String.IsNullOrEmpty(sub) || string.IsNullOrEmpty(text)) return -1;
            for (int i = 0; i < text.Length; i++)
            {
                if (sub[index] == text[i])
                {
                    if (index == 0) result = i;
                    index++;
                    if (index >= sub.Length) return result;
                }
                else
                {
                    index = 0;
                    if (result >= 0) i = result;
                    result = -1;
                }
            }
            return -1;
        }

        //Method for replacing all occurences of substring in
        public static string Replace(string text, string oldStr, string newStr)
        {
            var result = text;
            while (true)
            {
                var index = IndexOf(result, oldStr);
                if (index == -1) break;
                result = result.Substring(0, index) + newStr + result.Substring(index + oldStr.Length);
            }
            return result;
        }
    }

    //Class for getting the representation of a number in a computer's memory
    static class ComputerNumbers
    {
        static readonly char[] Binhex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        static readonly string[] Hexbin = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" };

        static readonly char[] HexChars = { 'A', 'B', 'C', 'D', 'E', 'F' };
        static readonly int[] HexNumeric = { 10, 11, 12, 13, 14, 15 };
        const int AsciiDiff = 48;

        //Int32 from decimal to any base
        public static string DecimalToBase(string Decimal, int toNumbase)
        {
            bool isNegativeNumber;
            if (Decimal.IndexOf('-') != -1)
            {
                isNegativeNumber = true;
                Decimal = Calc.Replace(Decimal, "-", string.Empty);
            }
            else isNegativeNumber = false;
            int dec = Calc.StringToInt(Decimal);
            string binaryString = "";
            var result = new int[32];
            int maxBit = 32;
            for (; dec > 0; dec /= toNumbase)
            {
                int rem = dec % toNumbase;
                result[--maxBit] = rem;
            }
            // ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 0; i < result.Length; i++)
                if (result[i] >= 10) binaryString += HexChars[result[i] % 10];
                else binaryString += result[i];
            binaryString = Kernel.TrimStart(binaryString, '0');
            if (isNegativeNumber) binaryString = binaryString.Insert(0, "-");
            return binaryString;
        }

        //Int32 from any base to decimal
        public static string BaseToDecimal(string number, int fromNumbase)
        {
            bool isNegativeNumber;
            if (number.IndexOf('-') != -1)
            {
                isNegativeNumber = true;
                number = Calc.Replace(number, "-", string.Empty);
            }
            else isNegativeNumber = false;
            int dec = 0;
            int product = 1;
            string hex = "";
            // ReSharper disable ForCanBeConvertedToForeach
            // ReSharper disable LoopCanBeConvertedToQuery
            if (fromNumbase > 10) for (int i = 0; i < HexChars.Length; i++) hex += HexChars[i].ToString();
            // ReSharper restore LoopCanBeConvertedToQuery
            // ReSharper restore ForCanBeConvertedToForeach
            for (int i = number.Length - 1; i >= 0; i--, product *= fromNumbase)
            {
                string sValue = number[i].ToString();
                int ind = number[i] - AsciiDiff;
                // ReSharper disable once ForCanBeConvertedToForeach
                // ReSharper disable once LoopCanBeConvertedToQuery
                for (int j = 0; j < HexChars.Length; j++)
                {
                    if (sValue.IndexOf(HexChars[j]) != -1)
                    {
                        ind = HexNumeric[hex.IndexOf(number[i])];
                        break;
                    }
                }
                dec += (ind * product);
            }
            string result = dec.ToString();
            if (isNegativeNumber) result = result.Insert(0, "-");
            return result;
        }

        //Int32 from any base to any base
        public static string SysConvert(string number, int fromNumbase, int toNumbase)
        {
            string convert = BaseToDecimal(number, fromNumbase);
            convert = DecimalToBase(convert, toNumbase);
            return convert;
        }

        // ReSharper disable once UnusedMember.Local
        //Representation of float in computer's memory
        public static string FloatToComp(string number, int fromNumbase, int memoryCell)
        {
            bool isNegativeNumber;
            number = number.Replace(',', '.');
            string[] intFracSplit = number.Split('.');
            if (intFracSplit[0].IndexOf('-') != -1)
            {
                isNegativeNumber = true;
                intFracSplit[0] = Calc.Replace(intFracSplit[0], "-", string.Empty);
            }
            else isNegativeNumber = false;
            string binary = "";
            string ext;
            string del;
            string[] spl;
            string dec = BaseToDecimal(intFracSplit[1], fromNumbase);
            int ipl = intFracSplit[0].Length;
            int msl;
            int mStep;

            if (Calc.StringToInt(intFracSplit[0]) == 0)
            {
                mStep = ipl + 64;
                msl = DecimalToBase(mStep.ToString(), 2).Length;
                for (int i = 0; i < memoryCell - msl - 2; i++)
                {
                    ext = "0." + dec;
                    del = (Calc.StringToFloat(ext) * 2).ToString();
                    spl = del.Split('.');
                    binary = binary + spl[0];
                    dec = del.IndexOf('.') != -1 ? spl[1] : "0";
                }
                binary = binary.Insert(0, DecimalToBase(mStep.ToString(), 2));
                binary = binary.Insert(0, isNegativeNumber ? "1" : "0");
                return binary;
            }
            string toBin = BaseToDecimal(intFracSplit[0], fromNumbase);
            binary = DecimalToBase(toBin, 2);
            int bl = binary.Length - 1;
            mStep = DecimalToBase(toBin, 2).Length + 64;
            msl = DecimalToBase(mStep.ToString(), 2).Length;
            for (int i = 0; i < memoryCell - bl - msl - 2; i++)
            {
                ext = "0." + dec;
                del = (Calc.StringToFloat(ext) * 2).ToString();
                spl = del.Split('.');
                binary = binary + spl[0];
                dec = del.IndexOf('.') != -1 ? spl[1] : "0";
            }
            binary = binary.Insert(0, DecimalToBase(mStep.ToString(), 2));
            binary = binary.Insert(0, isNegativeNumber ? "1" : "0");
            return binary;
        }

        // ReSharper disable once UnusedMember.Local
        //Overload: representation to any base
        public static string FloatToComp(string number, int fromNumbase, int memoryCell, int representationNumbase)
        {
            bool isNegativeNumber;
            number = number.Replace(',', '.');
            string[] intFracSplit = number.Split('.');
            if (intFracSplit[0].IndexOf('-') != -1)
            {
                isNegativeNumber = true;
                intFracSplit[0] = Calc.Replace(intFracSplit[0], "-", string.Empty);
            }
            else isNegativeNumber = false;
            string binary = "";
            string ext;
            string del;
            string[] spl;
            string dec = BaseToDecimal(intFracSplit[1], fromNumbase);
            int ipl = intFracSplit[0].Length;
            int msl;
            int mStep;

            if (Calc.StringToInt(intFracSplit[0]) == 0)
            {
                mStep = ipl + 64;
                msl = DecimalToBase(mStep.ToString(), 2).Length;
                for (int i = 0; i < memoryCell - msl - 2; i++)
                {
                    ext = "0." + dec;
                    del = (Calc.StringToFloat(ext) * 2).ToString();
                    spl = del.Split('.');
                    binary = binary + spl[0];
                    dec = del.IndexOf('.') != -1 ? spl[1] : "0";
                }
                binary = binary.Insert(0, DecimalToBase(mStep.ToString(), 2));
                binary = binary.Insert(0, isNegativeNumber ? "1" : "0");
                binary = SysConvert(binary, 2, representationNumbase);
                return binary;
            }
            string toBin = BaseToDecimal(intFracSplit[0], fromNumbase);
            binary = DecimalToBase(toBin, 2);
            int bl = binary.Length - 1;
            mStep = DecimalToBase(toBin, 2).Length + 64;
            msl = DecimalToBase(mStep.ToString(), 2).Length;
            for (int i = 0; i < memoryCell - bl - msl - 2; i++)
            {
                ext = "0." + dec;
                del = (Calc.StringToFloat(ext) * 2).ToString();
                spl = del.Split('.');
                binary = binary + spl[0];
                dec = del.IndexOf('.') != -1 ? spl[1] : "0";
            }
            binary = binary.Insert(0, DecimalToBase(mStep.ToString(), 2));
            binary = binary.Insert(0, isNegativeNumber ? "1" : "0");
            binary = SysConvert(binary, 2, representationNumbase);
            return binary;
        }

        //Float from any base to any base
        public static string FloatToSys(string number, int numbase, int resultNumbase)
        {
            bool isNegativeNumber;
            number = number.Replace(',', '.');
            var intFracSplit = number.Split('.');
            if (intFracSplit[0].IndexOf('-') != -1)
            {
                isNegativeNumber = true;
                intFracSplit[0] = Calc.Replace(intFracSplit[0], "-", string.Empty);
            }
            else isNegativeNumber = false;
            string num = "";
            string ext;
            string del;
            string[] spl;
            string dec = BaseToDecimal(intFracSplit[1], numbase);
            bool check = true;
            if (Calc.StringToInt(intFracSplit[0]) == 0)
            {
                int counterA = 0;
                while (check && counterA < 10)
                {
                    counterA++;
                    ext = "0." + dec;
                    del = (Calc.StringToFloat(ext) * resultNumbase).ToString();
                    spl = del.Split('.');
                    num = num + spl[0];
                    if (del.IndexOf('.') != -1) dec = spl[1];
                    else check = false;
                }
                num = num.Insert(0, "0.");
                if (isNegativeNumber) num = num.Insert(0, "-");
                return num;
            }
            string toBin = BaseToDecimal(intFracSplit[0], numbase);
            num = DecimalToBase(toBin, resultNumbase) + ".";
            int counterB = 0;
            while (check && counterB < 10)
            {
                counterB++;
                ext = "0." + dec;
                del = (Calc.StringToFloat(ext) * resultNumbase).ToString();
                spl = del.Split('.');
                num = num + spl[0];
                if (del.IndexOf('.') != -1) dec = spl[1];
                else check = false;
            }
            if (isNegativeNumber) num = num.Insert(0, "-");
            return num;
        }

        // ReSharper disable once UnusedMember.Local
        //Represention of Int32 in computer's memory
        public static string IntToComp(string number, int fromNumbase, int memoryCell)
        {
            int nl;
            if (number.IndexOf('-') != -1)
            {
                number = Calc.Replace(number, "-", string.Empty);
                number = SysConvert(number, fromNumbase, 2);
                nl = number.Length;
                for (int i = nl; i < memoryCell - 1; i++) number = number.Insert(0, "0");
                number = number.Insert(0, "1");
                nl = number.Length;
                for (int i = 1; i < nl; i++)
                {
                    if (number[i] == '1')
                    {
                        number = number.Remove(i, 1);
                        number = number.Insert(i, "0");
                    }
                    else
                    {
                        number = number.Remove(i, 1);
                        number = number.Insert(i, "1");
                    }
                }
                string ext = (Calc.StringToInt(BaseToDecimal(number, 2)) + 1).ToString();
                number = DecimalToBase(ext, 2);
                nl = number.Length;
                if (nl > memoryCell) number = number.Substring(nl - memoryCell, nl - (nl - memoryCell));
                return number;
            }
            number = SysConvert(number, fromNumbase, 2);
            nl = number.Length;
            for (int i = nl; i < memoryCell; i++) number = number.Insert(0, "0");
            return number;
        }

        // ReSharper disable once UnusedMember.Local
        //Overload: representation to any base
        public static string IntToComp(string number, int fromNumbase, int memoryCell, int representationNumbase)
        {
            int nl;
            if (number.IndexOf('-') != -1)
            {
                number = Calc.Replace(number, "-", string.Empty);
                number = SysConvert(number, fromNumbase, 2);
                nl = number.Length;
                for (int i = nl; i < memoryCell - 1; i++) number = number.Insert(0, "0");
                number = number.Insert(0, "1");
                nl = number.Length;
                for (int i = 1; i < nl; i++)
                {
                    if (number[i] == '1')
                    {
                        number = number.Remove(i, 1);
                        number = number.Insert(i, "0");
                    }
                    else
                    {
                        number = number.Remove(i, 1);
                        number = number.Insert(i, "1");
                    }
                }
                string ext = (Calc.StringToInt(BaseToDecimal(number, 2)) + 1).ToString();
                number = DecimalToBase(ext, 2);
                nl = number.Length;
                if (nl > memoryCell) number = number.Substring(nl - memoryCell, nl - (nl - memoryCell));
                number = SysConvert(number, 2, representationNumbase);
                return number;
            }
            number = SysConvert(number, fromNumbase, 2);
            nl = number.Length;
            for (int i = nl; i < memoryCell; i++) number = number.Insert(0, "0");
            number = SysConvert(number, 2, representationNumbase);
            return number;
        }

        // ReSharper disable once UnusedMember.Local
        //Returns the number from its HEX representation in computer's memory
        public static string FromHexRep(string representation, int resultNumbase)
        {
            string res = "";
            string result;
            // ReSharper disable once ForCanBeConvertedToForeach
            for (int i = 0; i < representation.Length; i++)
                for (int j = 0; j < 16; j++) if (representation[i] == Binhex[j]) res = res + Hexbin[j];
            if (res[0] != '1')
            {
                int dopol = Calc.StringToInt(BaseToDecimal(res, 2));
                result = DecimalToBase(dopol.ToString(), resultNumbase);
                return result;
            }
            else
            {
                int dopol = Calc.StringToInt(BaseToDecimal(res, 2)) - 1;
                res = DecimalToBase(dopol.ToString(), 2);
                int lng = res.Length;
                for (int i = 0; i < lng; i++)
                {
                    if (res[i] == '1')
                    {
                        res = res.Remove(i, 1);
                        res = res.Insert(i, "0");
                    }
                    else
                    {
                        res = res.Remove(i, 1);
                        res = res.Insert(i, "1");
                    }
                }
                int integer = Calc.StringToInt(BaseToDecimal(res, 2));
                result = "-" + DecimalToBase(integer.ToString(), resultNumbase);
                return result;
            }
        }

        // ReSharper disable once UnusedMember.Local
        //Range of variation of numbers in computer's memory
        //Memory cell in bits
        public static string RangeOfVariation(int memoryCell, bool isNegative, bool isPositive)
        {
            string result = "Error";
            if (isNegative && isPositive)
            {
                float st = Calc.StringToFloat(new Calc().Evaluate("2^"+(memoryCell-1)));
                result = "-" + st + " to " + (st - 1);
            }
            if (isNegative && isPositive == false)
            {
                float st = Calc.StringToFloat(new Calc().Evaluate("2^" + memoryCell));
                result = "-" + st + " to -1";
            }
            if (isNegative == false && isPositive)
            {
                float st = Calc.StringToFloat(new Calc().Evaluate("2^" + memoryCell));
                result = "0 to " + (st - 1);
            }
            return result;
        }

        // ReSharper disable once UnusedMember.Local
        //Normalized representation of float
        public static string Normalize(string number, int fromNumbase, int toNumbase)
        {
            number = number.Replace(',', '.');
            number = FloatToSys(number, fromNumbase, toNumbase);
            string[] spl = number.Split('.');
            string result = "0." + spl[0] + spl[1] + " * " + DecimalToBase(toNumbase.ToString(), toNumbase) + "^" + DecimalToBase(spl[0].Length.ToString(), toNumbase);
            return result;
        }
    }
    // ReSharper restore SpecifyACultureInStringConversionExplicitly
}